﻿using System;
using System.Collections.Generic;
using SX.Utils;

namespace SX.Redis.Generic
{
    /// <summary>
    /// Queue of commands for redis typed client
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class RedisTypedCommandQueue<T> : RedisQueueCompletableOperation
    {
        internal readonly RedisTypedClient<T> RedisClient;
        internal RedisTypedCommandQueue(RedisTypedClient<T> redisClient)
		{
			RedisClient = redisClient;

    	}
        
		public void QueueCommand(Action<IRedisTypedClient<T>> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Action<IRedisTypedClient<T>> command, Action onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Action<IRedisTypedClient<T>> command, Action onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
           		{
                    VoidReturnCommand = command,
           			OnSuccessVoidCallback = onSuccessCallback,
           			OnErrorCallback = onErrorCallback
           		});
			command(RedisClient);
		}


		public void QueueCommand(Func<IRedisTypedClient<T>, int> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, int> command, Action<int> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, int> command, Action<int> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
           	{
                IntReturnCommand = command,
           		OnSuccessIntCallback = onSuccessCallback,
           		OnErrorCallback = onErrorCallback
           	});
			command(RedisClient);
		}


		public void QueueCommand(Func<IRedisTypedClient<T>, long> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, long> command, Action<long> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, long> command, Action<long> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
			{
                LongReturnCommand = command,
				OnSuccessLongCallback = onSuccessCallback,
				OnErrorCallback = onErrorCallback
			});
			command(RedisClient);
		}


		public void QueueCommand(Func<IRedisTypedClient<T>, bool> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, bool> command, Action<bool> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, bool> command, Action<bool> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
           		{
                    BoolReturnCommand = command,
           			OnSuccessBoolCallback = onSuccessCallback,
           			OnErrorCallback = onErrorCallback
           		});
			command(RedisClient);
		}


		public void QueueCommand(Func<IRedisTypedClient<T>, double> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, double> command, Action<double> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, double> command, Action<double> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
               	{
                    DoubleReturnCommand = command,
               		OnSuccessDoubleCallback = onSuccessCallback,
               		OnErrorCallback = onErrorCallback
               	});
			command(RedisClient);
		}


		public void QueueCommand(Func<IRedisTypedClient<T>, byte[]> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, byte[]> command, Action<byte[]> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, byte[]> command, Action<byte[]> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
               	{
                    BytesReturnCommand = command,
               		OnSuccessBytesCallback = onSuccessCallback,
               		OnErrorCallback = onErrorCallback
               	});
			command(RedisClient);
		}


		public void QueueCommand(Func<IRedisTypedClient<T>, string> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, string> command, Action<string> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, string> command, Action<string> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
               	{
                    StringReturnCommand = command,
               		OnSuccessStringCallback = onSuccessCallback,
               		OnErrorCallback = onErrorCallback
               	});
			command(RedisClient);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, T> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, T> command, Action<T> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, T> command, Action<T> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
			{
                ObjectReturnCommand = command,
				OnSuccessTypeCallback = x => onSuccessCallback(JsonSerializer.DeserializeFromString<T>(x)),
				OnErrorCallback = onErrorCallback
			});
			command(RedisClient);
		}


		public void QueueCommand(Func<IRedisTypedClient<T>, byte[][]> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, byte[][]> command, Action<byte[][]> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, byte[][]> command, Action<byte[][]> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
               	{
                    MultiBytesReturnCommand = command,
               		OnSuccessMultiBytesCallback = onSuccessCallback,
               		OnErrorCallback = onErrorCallback
               	});
			command(RedisClient);
		}


		public void QueueCommand(Func<IRedisTypedClient<T>, List<string>> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, List<string>> command, Action<List<string>> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, List<string>> command, Action<List<string>> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
               	{
                    MultiStringReturnCommand = command,
               		OnSuccessMultiStringCallback = onSuccessCallback,
               		OnErrorCallback = onErrorCallback
               	});
			command(RedisClient);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, List<T>> command)
		{
			QueueCommand(command, null, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, List<T>> command, Action<List<T>> onSuccessCallback)
		{
			QueueCommand(command, onSuccessCallback, null);
		}

		public void QueueCommand(Func<IRedisTypedClient<T>, List<T>> command, Action<List<T>> onSuccessCallback, Action<Exception> onErrorCallback)
		{
			BeginQueuedCommand(new QueuedRedisTypedCommand<T>
			{
                MultiObjectReturnCommand = command,
				OnSuccessMultiTypeCallback = x => onSuccessCallback(x.ConvertAll(y => JsonSerializer.DeserializeFromString<T>(y))),
				OnErrorCallback = onErrorCallback
			});
			command(RedisClient);
		}

    }
}
